package iotwisp.base.rest;

import iotwisp.base.cqrs.*;
import iotwisp.base.util.JSONUtils;
import iotwisp.base.util.SpringContextUtil;
import iotwisp.base.jwt.JwtConfig;
import iotwisp.base.orm.query.pagination.Pagination;
import iotwisp.base.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 控制器基类
 *
 * @author yuxx
 */
@Slf4j
public class RestBaseController {

    public static final Logger logger = LoggerFactory.getLogger(RestBaseController.class);

    @SuppressWarnings("rawtypes")
    public void preHandle(HttpServletRequest request, BaseQO qo) {

    }

    public void preHandle(HttpServletRequest request, BaseCommand command) {

    }

    /**
     * 自动将yyyy-MM-dd格式的参数转换成Date型参数
     */
    @InitBinder
    @SuppressWarnings("rawtypes")
    public void initBinder(WebDataBinder binder, HttpServletRequest request) {
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat1.setLenient(true);

        SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat2.setLenient(true);

        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat1, true));
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat2, true));

        if (binder.getObjectName().indexOf("QO") != -1) {
            BaseQO qo = (BaseQO) binder.getTarget();
            if (qo != null) {
                preHandle(request, qo);
            }
        } else if (binder.getObjectName().indexOf("Command") != -1) {
            BaseCommand command = (BaseCommand) binder.getTarget();
            if (command != null) {
                preHandle(request, command);
            }
        }
    }

    public static JSONResultDTO createSuccessResult(Object resultData) {
        if (resultData instanceof Pagination) {
            ((Pagination) resultData).setCondition(null);
        }
        return createSuccessResult(resultData, true);
    }

    public static JSONResultDTO createSuccessResult(Object resultData, boolean hibernateProxyRemove) {
        if (resultData instanceof Pagination) {
            ((Pagination) resultData).setCondition(null);
        }

        JSONResultDTO result = new JSONResultDTO();
        result.setCode("0");
        result.setMsg("请求成功");
        result.setData(resultData);

//        if (hibernateProxyRemove) {
//            result = JSONUtils.transform(result, JSONResultDTO.class);
//        }

        result = JSONUtils.transform(result, !hibernateProxyRemove, JSONResultDTO.class);

        return result;
    }

    public static JSONResultDTO createFailResult(String code, String message, Object resultData) {
        JSONResultDTO result = new JSONResultDTO();
        result.setCode(code);
        result.setMsg(message);
        result.setData(resultData);
        return result;
    }

    protected String getSuffixName(String fullName) {
        String suffixName;
        int index = fullName.lastIndexOf(".");
        suffixName = fullName.substring(index);
        return suffixName;
    }

    /**
     * 获取clientIp
     */
    public String getClientIp(HttpServletRequest request) {

        // 获取Ip
        String clientIP = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(clientIP) || "unknown".equalsIgnoreCase(clientIP)) {
            clientIP = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(clientIP) || "unknown".equalsIgnoreCase(clientIP)) {
            clientIP = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(clientIP) || "unknown".equalsIgnoreCase(clientIP)) {
            clientIP = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(clientIP) || "unknown".equalsIgnoreCase(clientIP)) {
            clientIP = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(clientIP) || "unknown".equalsIgnoreCase(clientIP)) {
            clientIP = request.getRemoteAddr();
        }

        logger.info("ip:{}", clientIP);

        return clientIP;
    }

    protected String getCurrentUserId(String accessToken, TraceHeader header) throws BusinessException {

        JwtConfig jwtConfig = (JwtConfig) SpringContextUtil.getBean("jwtConfig");

        try {
            if (header != null && StringUtils.isNotBlank(header.getClientId())) {
                String loginClientId = JwtUtil.getValue(accessToken, jwtConfig.getSecret(), "clientId");
                if (!StringUtils.equals(header.getClientId(), loginClientId)) {
                    throw BusinessException.getInstance(BusinessException.NO_LOGIN, "非本客户端登录");
                }
            }
            String userId = JwtUtil.parseJWT(accessToken, jwtConfig.getSecret()).getSubject();
            if (StringUtils.isBlank(userId)) {
                throw BusinessException.getInstance(BusinessException.NO_LOGIN, "未登录");
            }
            return userId;
        } catch (Exception e) {
            throw BusinessException.getInstance(BusinessException.NO_LOGIN, "未登录");
        }

    }

    protected void initHeader(SPIBaseCommand cmd, HttpServletRequest request) {
        if (request.getAttribute("traceHeader") != null) {
            cmd.setHeader((TraceHeader) request.getAttribute("traceHeader"));
        }
        log.info("cmd:{}", JSONUtils.toJSONString(cmd, true));
    }

    protected boolean initHeader(SPIBaseQO qo, HttpServletRequest request) {
        if (request.getAttribute("traceHeader") != null) {
            qo.setHeader((TraceHeader) request.getAttribute("traceHeader"));
            if (qo.getHeader().getClientId().equals("pc-admin")) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }
}
